﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using Bouyei.Geo;
using System.IO;
using Bouyei.DbFactory;
using Esri.FileGDB;
 
namespace Bouyei.Demo
{
    using Bouyei.Geo.Geometries;
    using Bouyei.Geo.GeoParsers.Parser;
    using Bouyei.Geo.GeoParsers.EsriJson;

    class Program
    {
        static void Main(string[] args)
        {
            //TestSpatiaLite(@"F:\dxm.sqlite");
            //TestGeoPackage(@"F:\geopackage.gpkg");

            //TestVctFormat();

            TestDbf();

            //TestEsriJson();

            //TestGeoJson();

            //var item=JsonPaser.Json.Parse("{\"type\": \"Feature\",\"geometry\": {\"type\": \"Point\",\"coordinates\": [125.6, 10.1]},\"properties\": {\"name\": \"Dinagat Islands\"}}");

            //TestFromEsriMdb();

            //TestFromWKT();

            TestFromEsriGdb();

            TestWkbFromPg();

           // TestPrjParser();

            TestArea();
            //TestShpfile();
        }

        static void TestWkbFromPg()
        {
            string connstr = "Server=127.0.0.1;Port=5432;User Id=postgres;Password=bouyei;Database=msg;";
            using (IAdoProvider provider = AdoProvider.CreateProvider(connstr, FactoryType.PostgreSQL))
            {
                var param = new Parameter("select cjdm,cjmc,ST_AsEWKB(geom) as ewkb from cn_xzq");
                var tb = provider.Query(param);

                var rt = provider.Query<cn_xzq>(param);
                if (rt.IsSuccess() == false)
                    throw new Exception(rt.Info);

                var items = rt.Result;
                foreach(var item in items)
                { 
                    string a = string.Join(",", item.ewkb);
                    PostGISParser parser = new PostGISParser();
                    var geo= parser.FromReader(item.ewkb);

                    //坐标转换
                    //var ngeo = new GeoBase().ToPlaneCoordinates(geo);
                    //var ggeo = new GeoBase().ToGeoCoordinates(ngeo);
                     var arry=parser.ToWriter(geo);

                    for(int i = 0; i < item.ewkb.Length;++i)
                    {
                        if (item.ewkb[i] != arry[i])
                        {
                            throw new Exception(i.ToString()+"不匹配");
                        }
                    }
                    Console.Write("匹配："+geo.GeometryType.ToString());
                    //string b = string.Join(",", arry);
                }

                //List<Geometry> geos = new List<Geometry>();
                //foreach (var item in items)
                //{
                //    WkbParser wkbParser = new WkbParser();
                //    var geo = wkbParser.FromReader(item.wkb);
                //    geos.Add(geo);
                //}
            }
        }

        static void TestVctFormat()
        {
            VctParser vct = new VctParser(Encoding.GetEncoding("GB2312"));
            var vctInfo = vct.FromReader(@"E:\2001H2019522623.vct");
        }

        //支持mdb和gdb字节解析
        static void TestFromEsriMdb()
        {
            string connstr = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=F:\\g.mdb;";
            using (IAdoProvider provider = AdoProvider.CreateProvider(connstr, FactoryType.OleDb))
            {
                var rt = provider.Query<Item>(new Parameter("select top 1 SHAPE as wkb from mpoint"));
                var items = rt.Result;
                List<Geometry> geos = new List<Geometry>();
                foreach (var item in items)
                {
                    EsriMdbParser wkbParser = new EsriMdbParser();
                    //解析和反解析字节
                    var geo = wkbParser.FromReader(item.wkb);
                    var buf = wkbParser.ToWriter(geo);
                    var ngeo = wkbParser.FromReader(buf);

                    //生成wkt
                    string wkt = geo.ToWkt();

                    geos.Add(geo);
                }
            }
        }

        static void TestFromEsriGdb()
        {
            //EsriMdbParser gparser = new EsriMdbParser();
            //byte[] dbuf = new byte[] { 5, 0, 0, 0, 104, 51, 179, 219, 118, 45, 90, 64, 16, 81, 17, 195, 232, 78, 59, 64, 191, 75, 74, 144, 125, 45, 90, 64, 239, 220, 173, 57, 251, 78, 59, 64, 1, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 204, 33, 115, 73, 123, 45, 90, 64, 224, 220, 173, 57, 251, 78, 59, 64, 228, 170, 44, 182, 123, 45, 90, 64, 224, 220, 173, 57, 251, 78, 59, 64, 216, 214, 242, 68, 124, 45, 90, 64, 80, 206, 45, 58, 250, 78, 59, 64, 32, 74, 120, 56, 125, 45, 90, 64, 0, 43, 54, 60, 246, 78, 59, 64, 228, 58, 87, 120, 125, 45, 90, 64, 160, 104, 91, 253, 243, 78, 59, 64, 192, 75, 74, 144, 125, 45, 90, 64, 48, 166, 128, 190, 241, 78, 59, 64, 248, 90, 107, 80, 125, 45, 90, 64, 192, 100, 151, 160, 237, 78, 59, 64, 16, 82, 217, 120, 124, 45, 90, 64, 96, 80, 112, 2, 234, 78, 59, 64, 128, 110, 13, 17, 124, 45, 90, 64, 80, 35, 174, 130, 233, 78, 59, 64, 40, 30, 147, 9, 123, 45, 90, 64, 144, 50, 207, 66, 233, 78, 59, 64, 40, 245, 236, 89, 122, 45, 90, 64, 80, 35, 174, 130, 233, 78, 59, 64, 128, 76, 151, 10, 121, 45, 90, 64, 224, 4, 108, 2, 234, 78, 59, 64, 180, 223, 232, 106, 120, 45, 90, 64, 160, 95, 145, 194, 233, 78, 59, 64, 216, 163, 65, 187, 119, 45, 90, 64, 16, 81, 17, 195, 232, 78, 59, 64, 108, 175, 130, 59, 119, 45, 90, 64, 16, 81, 17, 195, 232, 78, 59, 64, 72, 70, 180, 219, 118, 45, 90, 64, 224, 110, 178, 130, 233, 78, 59, 64, 104, 51, 179, 219, 118, 45, 90, 64, 176, 34, 13, 194, 234, 78, 59, 64, 196, 131, 45, 227, 119, 45, 90, 64, 80, 68, 114, 222, 241, 78, 59, 64, 60, 193, 166, 234, 120, 45, 90, 64, 240, 185, 6, 156, 246, 78, 59, 64, 24, 172, 50, 210, 121, 45, 90, 64, 96, 124, 225, 218, 248, 78, 59, 64, 92, 177, 228, 105, 122, 45, 90, 64, 160, 10, 17, 122, 250, 78, 59, 64, 196, 165, 163, 233, 122, 45, 90, 64, 224, 220, 173, 57, 251, 78, 59, 64, 204, 33, 115, 73, 123, 45, 90, 64, 224, 220, 173, 57, 251, 78, 59, 64 };
            //var r = gparser.FromReader(dbuf);

            string gdbfile = @"F:\czfw2019.gdb";
            using (Geodatabase geodb = Geodatabase.Open(gdbfile))
            {
                var rows = geodb.ExecuteSQL("select * from czfw where bsm=413931");
                foreach (var row in rows)
                {

                    var buf = row.GetGeometry().shapeBuffer;
                    var gt = row.GetGeometry().geometryType;

                    EsriMdbParser gdb = new EsriMdbParser();
                    var geo = gdb.FromReader(buf);
                    var rbuf= gdb.ToWriter(geo);
                    var wkt = geo.ToWkt();
                }
            }
        }

        static void TestFromWKT()
        {
            string wkt = "MULTIPOLYGON Z ((( 36380322.94190000 3009285.90240000 0.00000000, 36380330.39850000 3009288.54560000 0.00000000, 36380337.75920000 3009291.16280000 0.00000000, 36380343.86390000 3009294.77820000 0.00000000, 36380340.98420000 3009293.62630000 0.00000000, 36380336.65990000 3009292.68620000 0.00000000, 36380328.35730000 3009290.88140000 0.00000000, 36380323.82440000 3009292.21450000 0.00000000, 36380321.45320000 3009291.38880000 0.00000000, 36380314.36510000 3009287.24500000 0.00000000, 36380306.51370000 3009282.44690000 0.00000000, 36380301.79640000 3009279.46250000 0.00000000, 36380297.42540000 3009275.84790000 0.00000000, 36380294.70850000 3009271.77280000 0.00000000, 36380288.08470000 3009261.83700000 0.00000000, 36380268.34710000 3009242.20840000 0.00000000, 36380265.65910000 3009239.10920000 0.00000000, 36380260.89710000 3009233.61860000 0.00000000, 36380260.24620000 3009233.02720000 0.00000000, 36380249.61820000 3009223.37050000 0.00000000, 36380234.47530000 3009209.30920000 0.00000000, 36380211.47940000 3009190.29340000 0.00000000, 36380187.57020000 3009174.84430000 0.00000000, 36380180.15490000 3009169.28290000 0.00000000, 36380157.47310000 3009150.52680000 0.00000000, 36380135.50460000 3009132.15790000 0.00000000, 36380131.10180000 3009129.58960000 0.00000000, 36380127.61220000 3009128.06300000 0.00000000, 36380124.63920000 3009126.63810000 0.00000000, 36380122.05080000 3009125.39750000 0.00000000, 36380120.81190000 3009124.51250000 0.00000000, 36380115.68200000 3009120.84830000 0.00000000, 36380104.76400000 3009110.61270000 0.00000000, 36380094.18720000 3009094.46320000 0.00000000, 36380086.22620000 3009081.49810000 0.00000000, 36380079.06120000 3009072.17230000 0.00000000, 36380077.35530000 3009070.23890000 0.00000000, 36380067.40170000 3009062.13450000 0.00000000, 36380062.37500000 3009058.25480000 0.00000000, 36380060.61940000 3009056.43760000 0.00000000, 36380056.15930000 3009051.82100000 0.00000000, 36380046.34500000 3009044.54210000 0.00000000, 36380041.92860000 3009041.92500000 0.00000000, 36380036.20360000 3009039.47140000 0.00000000, 36380031.13290000 3009037.50850000 0.00000000, 36380026.71650000 3009036.69070000 0.00000000, 36380022.46360000 3009035.87280000 0.00000000, 36380016.73860000 3009033.91000000 0.00000000, 36380009.37790000 3009031.62000000 0.00000000, 36380004.38140000 3009030.48720000 0.00000000, 36380004.94620000 3009028.22810000 0.00000000, 36380003.20640000 3009022.42880000 0.00000000, 36380023.67890000 3009027.09090000 0.00000000, 36380029.59280000 3009028.79680000 0.00000000, 36380033.23210000 3009030.16150000 0.00000000, 36380050.29150000 3009039.48730000 0.00000000, 36380055.68330000 3009042.35380000 0.00000000, 36380059.27610000 3009044.26390000 0.00000000, 36380066.03580000 3009049.94610000 0.00000000, 36380067.12340000 3009050.86020000 0.00000000, 36380084.18270000 3009064.28020000 0.00000000, 36380088.16320000 3009069.39800000 0.00000000, 36380092.14370000 3009075.42570000 0.00000000, 36380102.83420000 3009092.03010000 0.00000000, 36380107.26970000 3009098.85380000 0.00000000, 36380112.34900000 3009105.27550000 0.00000000, 36380115.62040000 3009108.21980000 0.00000000, 36380120.52760000 3009112.79970000 0.00000000, 36380123.30830000 3009115.74400000 0.00000000, 36380135.47460000 3009128.28470000 0.00000000, 36380150.30770000 3009138.19990000 0.00000000, 36380171.23460000 3009157.29110000 0.00000000, 36380191.19030000 3009172.66680000 0.00000000, 36380221.77810000 3009193.11320000 0.00000000, 36380242.38810000 3009210.94250000 0.00000000, 36380260.54450000 3009229.09890000 0.00000000, 36380265.66970000 3009232.86780000 0.00000000, 36380265.93270000 3009233.11080000 0.00000000, 36380268.82920000 3009235.78780000 0.00000000, 36380271.96270000 3009238.68370000 0.00000000, 36380276.73810000 3009243.32960000 0.00000000, 36380284.23990000 3009251.58850000 0.00000000, 36380290.08780000 3009258.02650000 0.00000000, 36380291.98040000 3009260.51800000 0.00000000, 36380301.89940000 3009273.57520000 0.00000000, 36380308.92100000 3009279.05210000 0.00000000, 36380314.41790000 3009281.95450000 0.00000000, 36380314.60480000 3009282.03460000 0.00000000, 36380318.82220000 3009284.14040000 0.00000000, 36380320.90490000 3009285.18030000 0.00000000, 36380322.94190000 3009285.90240000 0.00000000)),(( 36380598.56780000 3009539.06510000 0.00000000, 36380595.64970000 3009542.44090000 0.00000000, 36380591.36660000 3009540.62290000 0.00000000, 36380591.63990000 3009540.44070000 0.00000000, 36380594.51080000 3009536.99550000 0.00000000, 36380594.96910000 3009536.65950000 0.00000000, 36380598.56780000 3009539.06510000 0.00000000)))";
            var rt = new WktParser().Reader(wkt);

        }
        class jsonattr
        {
            public int OBJECTID { get; set; }
        }

        static void TestArea()
        {
            //string str = File.ReadAllText("E:\\holepart.json");

            //GeoJsonParser geojson = new GeoJsonParser(str);
            //var item= geojson.FromReaderToFeatureCollection<jsonattr,JsonPolygon>();
            //foreach (var f in item.features)
            //{

            //}

            GeoBase gbase = new GeoBase();
           var b= gbase.XYtoLB(new Coordinate() { 
             X= 35371648.1539,
             Y=2942106.55
            });

           var XY= gbase.LBtoXY(new Coordinate() { 
             X= 107.04444,
             Y= 27.03083
            });
            var XY1 = gbase.LBtoXY(new Coordinate()
            {
                X = 107.04444,
                Y = 27.025
            });
            var XY2 = gbase.LBtoXY(new Coordinate()
            {
                X = 107.04972,
                Y = 27.03083
            });
            var XY3 = gbase.LBtoXY(new Coordinate()
            {
                X = 107.04972,
                Y = 27.025
            });

            string wktstr =string.Empty;//  File.ReadAllText("E:\\wkthole.txt");
            wktstr = "POLYGON ((105.66278148717595 26.268896196702144,105.65603151224457 26.270494874738745,105.6553345349609 26.27166525334883,105.65733907973481 26.273402525905908,105.6625862344672 26.271431379254807,105.66278148717595 26.268896196702144))";
            WktParser wkt = new WktParser();
            var inter= wkt.FromReader(wktstr).First();

            Geometry geometry = new Geometry(GeoType.POLYGON, inter);
            var seq= geometry.GetSequence(0, 0);
            var seq2 = geometry.GetSequence(0, 1);

            var dir= seq.GetOrientation();
            var dir12 = seq2.GetOrientation();

            //string wktstr = "POLYGON((0 0,0 2,2 2,2 0,0 0))";
            //using (FileStream fs = new FileStream("D:\\wkt.txt", FileMode.Open))
            //{
            //    using (StreamReader reader = new StreamReader(fs))
            //    {
            //        wktstr = reader.ReadToEnd();
            //    }
            //}

            GeoPlane plane = new GeoPlane();
            var area = plane.Area(wktstr);

            GeoEllipsoid geo = new GeoEllipsoid();
            var ellipse = geo.Area(wktstr);

            var dist = geo.Distance(new Coordinate()
            {
                X = 36379440.1493,
                Y = 2936717.206599999
            },
             new Coordinate()
             {
                 X = 36379425.4384,
                 Y = 2936710.4860999994
             });

            var geopoint = new Coordinate()
            {
                X = 36367729.9624,
                Y = 2941185.8308
            };

            var bl = plane.XYtoLB(geopoint);
            var bxy = plane.LBtoXY(bl);
        }

        static void TestPrjParser()
        {
            string file =@"F:\\prj.xml";
           var r= new ProjParser().FromReader(file);
        }

        static void TestEsriJson()
        {
            string esriJson = "{\"hasZ\":false,\"hasM\":false,\"rings\":[[[36368489.5775,2935352.9713],[36368486.6894,2935345.1954],[36368484.533,2935330.6949],[36368482.9081,2935309.6944],[36368484.0017,2935297.1944],[36368484.0016,2935288.6944],[36368480.7514,2935278.9444],[36368470.5011,2935271.4441],[36368458.6567,2935258.944],[36368446.7812,2935249.1943],[36368437.5934,2935239.9446],[36368427.9055,2935226.6948],[36368419.8116,2935214.695],[36368411.718,2935204.4452],[36368404.1555,2935198.4455],[36368397.1554,2935191.9455],[36368386.374,2935186.6958],[36368379.9053,2935184.9461],[36368369.0927,2935180.1963],[36368365.3114,2935174.1961],[36368359.9365,2935165.696],[36368359.9366,2935155.4459],[36368364.2491,2935146.196],[36368370.7184,2935105.1951],[36368385.2812,2935065.9435],[36368393.375,2935038.4425],[36368397.6874,2935021.1923],[36368397.687,2935011.4423],[36368397.6868,2935003.1923],[36368397.1554,2934997.4422],[36368396.6241,2934990.4422],[36368389.5922,2934969.192],[36368385.8109,2934961.692],[36368369.0915,2934938.4417],[36368357.2477,2934924.9419],[36368352.3728,2934919.1919],[36368346.9978,2934908.9419],[36368346.9978,2934900.1918],[36368346.9979,2934892.1918],[36368350.2168,2934882.9415],[36368357.2482,2934867.4413],[36368365.3108,2934851.6911],[36368366.4047,2934845.1911],[36368367.4984,2934835.9411],[36368368.5611,2934823.6911],[36368369.6549,2934813.941],[36368375.03,2934797.1909],[36368392.2803,2934769.6908],[36368406.3116,2934744.4408],[36368420.3431,2934725.9408],[36368420.6541,2934725.4236],[36368404.4669,2934728.3564],[36368368.3133,2934740.2367],[36368335.1909,2934758.5407],[36368305.5548,2934777.7161],[36368286.9593,2934793.2122],[36368284.6355,2934795.1485],[36368267.2032,2934816.9396],[36368259.3587,2934842.217],[36368253.2574,2934872.7246],[36368251.5141,2934901.4889],[36368250.4808,2934917.5076],[36368249.7709,2934928.5097],[36368248.8994,2934950.3008],[36368253.6258,2934988.5533],[36368254.2459,2934992.4801],[36368255.7168,2935001.7975],[36368262.6873,2935026.1945],[36368264.7784,2935049.8945],[36368265.5902,2935063.2849],[36368266.1729,2935072.8973],[36368264.7789,2935089.6268],[36368259.8996,2935107.0531],[36368255.9602,2935115.5886],[36368251.5349,2935125.1764],[36368245.2612,2935134.2381],[36368245.2613,2935150.9675],[36368245.2614,2935166.9998],[36368251.5352,2935183.0322],[36368257.8087,2935201.8527],[36368262.6883,2935214.3998],[36368263.3852,2935229.7351],[36368263.295,2935230.9094],[36368261.9911,2935247.8585],[36368260.5966,2935272.2554],[36368264.7788,2935289.6819],[36368273.1451,2935307.2567],[36368282.8889,2935321.0126],[36368284.585,2935323.407],[36368295.9042,2935333.0297],[36368311.5107,2935335.1823],[36368340.5709,2935343.793],[36368355.1013,2935354.5562],[36368363.7119,2935358.3233],[36368369.0933,2935353.4799],[36368370.7076,2935347.0222],[36368370.5162,2935345.6828],[36368369.6311,2935339.4882],[36368378.7796,2935331.9539],[36368395.4626,2935331.9536],[36368427.7525,2935331.9529],[36368454.1226,2935336.7959],[36368489.5775,2935352.9713]]],\"spatialReference\":{\"wkid\":4523}}";
            EsriJsonParser json = new EsriJsonParser();
            var geo=json.FromReader(esriJson);
            var str = json.ToWriter(geo);
        }

        static void TestGeoJson()
        {
            string geoJson = "{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-73.981149,40.7470284],[-73.9831414,40.7341684],[-74.0053897,40.7343148],[-74.0047921,40.7502785],[-73.981149,40.7470284]]]]}";
            GeoJsonParser json = new  GeoJsonParser();
            var geo = json.FromReader(geoJson);
            var str = json.ToWriter(geo);
        }

        static void TestDbf()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("name", typeof(string));
            dt.Columns.Add("age", typeof(int));
            dt.Columns.Add("score", typeof(float));
            dt.Columns.Add("range", typeof(double));
            dt.Columns.Add("date", typeof(DateTime));

            dt.Rows.Add(new object[] { "abb", 123, 99999.421f,12.4444 ,DateTime.Now });
            dt.Rows.Add(new object[] { "ccc", 13, 33.44f, 12.5555,DateTime.Now });
            dt.Rows.Add(new object[] { "第df方", 12, 33.45f, 12.6666666,DateTime.Now });

            List<attr> list = new List<attr>();
            list.Add(new attr() {
                code = "和",
                name = "sdf",
            });
            list.Add(new attr() { 
            code="dsfasd1321",
             name="sdf对方"
            });

            DbfParser dbf = new DbfParser( Encoding.GetEncoding("GB2312"));
            //dbf.ToWrite<attr>(list, null);

            dbf.ToWriter("test1.dbf",dt);
        }

        static void TestShpfile()
        {
            string file = "F:\\县级行政区4.shp";
            ShpParser parser = new ShpParser();
            var geos= parser.FromReader(file);

            File.WriteAllText("f:\\test.wkt", geos.Features[0].geometry.ToWkt());
        }

        static void TestSpatiaLite(string sqlite)
        {
            string connstr = $"Data Source={sqlite};Version=3;Read Only=True;Pooling=False;Max Pool Size=100;";
            using (var provider = AdoProvider.CreateProvider(connstr, FactoryType.SQLite))
            {
                var rt = provider.Query<SpatiaLiteGeo>(new Parameter("select * from mian"));
                if (rt.IsSuccess() == false)
                    throw new Exception(rt.Info);

                SpatiaLiteParser parser = new SpatiaLiteParser();

                foreach (var item in rt.Result)
                {
                    //解析spatialite 字节
                    var geo = parser.FromReader(item.GEOMETRY);

                    //还原为spatialite字节
                    var geo_buffer= parser.ToWriter(geo);

                    Console.WriteLine(geo.ToWkt());
                }
            }
        }

        static void TestGeoPackage(string sqlite)
        {
            string connstr = $"Data Source={sqlite};Version=3;Read Only=True;Pooling=False;Max Pool Size=100;";
            using (var provider = AdoProvider.CreateProvider(connstr, FactoryType.SQLite))
            {
                var rt = provider.Query<GeoPackageGeo>(new Parameter("select * from xian"));
                if (rt.IsSuccess() == false)
                    throw new Exception(rt.Info);

                GeoPackageParser parser = new  GeoPackageParser();

                foreach (var item in rt.Result)
                {
                    //还原为geopackage字节
                    var geo = parser.FromReader(item.geom);
                    Console.WriteLine(geo.ToWkt());

                    //还原为geopackage字节
                    var geo_buffer = parser.ToWriter(geo);

                    //测试writer方法结果
                    var g=parser.FromReader(geo_buffer);

                    Console.WriteLine(geo.ToWkt());
                }
            }
        }
    }

    public class attr
    {
        public string name { get; set; }

        public string code { get; set; }
    }

    public class Item
    {
        public string bsm { get; set; }

        public byte[] wkb { get; set; }

    }

    public class cn_xzq
    {
        public string cjdm { get; set; }

        public string cjmc { get; set; }

        public byte[] ewkb { get; set; }
    }

    public class SpatiaLiteGeo
    {
        public float x { get; set; }

        public float y { get; set; }

        public byte[] GEOMETRY { get; set; }
    }

    public class GeoPackageGeo
    {
        public byte[] geom { get; set; }
    }

}
